package win.ganbo.easyframwork.repository;

import java.io.Serializable;
import java.util.Collections;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.data.repository.NoRepositoryBean;

@NoRepositoryBean
public class BaseRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T, ID>
		implements BaseRepository<T, ID> {

	private EntityManager entityManager;
	private Class<T> domainClass;
	
	private static final String SQL_COUNT = "SELECT COUNT(1) ";
	private static final String SQL_LIST = "SELECT o  ";
	private static final String SQL_ORDER = " ORDER BY ";

	public BaseRepositoryImpl(Class<T> domainClass, EntityManager em) {
		super(domainClass, em);
		this.entityManager = em;
		this.domainClass = domainClass;
	}
	
	private void prepareQueryParam(Query query, List<Object> params) {
		if (params != null && params.size() > 0) {
			for (int i = 0; i < params.size(); i++) {
				query.setParameter(i + 1, params.get(i));
			}
		}
	}

	
	@SuppressWarnings("unchecked")
	@Override
	public Page<T> getResultPageByQuery(String hql, Pageable pageable, List<Object> params) {
		String countQryS = SQL_COUNT + hql;

		Query countQry = entityManager.createQuery(countQryS);
		prepareQueryParam(countQry, params);

		long total = (Long) (countQry.getSingleResult());

		List<T> result = null;
		if (total > pageable.getOffset()) {
			StringBuilder qryS = new StringBuilder();
			qryS.append(SQL_LIST);
			qryS.append(hql);
			
			if (pageable.getSort() != null) {// 处理排序问题
				qryS.append(SQL_ORDER);
				for (Sort.Order order : pageable.getSort()) {
					qryS.append(order.getProperty()).append(" ");
					qryS.append(order.getDirection().toString());
				}
			}
			Query query = entityManager.createQuery(qryS.toString(), domainClass);
			prepareQueryParam(query, params);
			query.setFirstResult(pageable.getOffset());
			query.setMaxResults(pageable.getPageSize());
			result = query.getResultList();

		} else { // 总数小于开始下标就返回空集合
			result = Collections.emptyList();
		}
		return new PageImpl<>(result, pageable, total);
	}
	
	

	@SuppressWarnings("unchecked")
	@Override
	public List<T> findByHql(String hql, List<Object> params) {
		Query query = entityManager.createQuery(hql,domainClass);
		prepareQueryParam(query, params);
		List<T> resultList = query.getResultList();
		return resultList;
	}

}
